调研 Federated Modules,应用秒开,应用集方案,微前端加载方案改进等
昨天看到的,好久没看到这么令人心动的功能了,感觉可能会改变未来几年的打包方式。同时可以解一些我们目前面临的问题,比如编译提速,应用集群方案,微前端方案改进。
是什么?
大家可以先看下这篇文章(https://www.bram.us/2020/03/12/introducing-federated-modules-in-webpack-5/)中的视频,解释地很清楚。
我的理解,
Webpack 5 的新特性,允许在多个 webpack 编译产物之间共享模块、依赖、页面甚至应用
提供了一种轻量级的运行时,通过全局变量组合,有种之前用 seajs 的感觉
提供了一种解决应用集的官方方案
应用场景
看到的介绍文章里更多说的是在微前端方面的加载改进,我结合我们遇到问题说下我想到的应用场景。
编译提速,秒开(10 s 内)
Shared library
感觉之前想做的 Bundlerless 一下子没那么重要了。
试验了一把 react + react-dom + antd,remote 外部依赖全部 remote 掉,1.59s 完成编译。
示例仓库:https://github.com/sorrycc/test-federated-modules
先拆了一个应用专门做依赖打包,把 react, react-dom 和 antd 打进去;另一个应用使用这些依赖的时候配 remote,不做实际打包,通过 runtime 的方式引之前打包好的文件。
和 external 的区别?
external 需要自行在 html 引入相关 script,此方案只需引一个 runtime 文件,runtime 里维护了 chunk 的映射表
external 需要自行处理库的依赖,比如 antd 依赖 moment,那么就需要分别引 moment 和 antd 的 umd 文件,并且保证顺序
external 没法拆包,比如 antd 只能引一个大的 antd,此方案可以拆,比如只用了 Button,可以不引整个 antd
此外,
结合平台可以做一些自动化的事情,可以发挥更大价值。比如自动把我们的常用依赖定期打包,然后大家不管是开发环境还是生产环境都依赖统一的 runtime。打包可以是打大包,比如 ant-design-pro 可以把相关的;也可以是打小包,然后利用 cdn 的 combo 机制合到一起,如果是打小包,大量重复的 runtime 合一起还是有点大,需要提下
Umi 内置的开发依赖比如 socket.io、webpack-hot-middleware、@babel/runtime、core-js 等也可以提前打出来通过 runtime 的方式引入
和此前大量利用缓存的方案不同,不是二次编译快,而是首次编译就快
可以支持多版本,比如同时有 antd 3 和 antd 4
codesandbox 之前做过 webpack dll 的 cdn,我觉得和这个的思路很像,常用依赖全部上 cdn,项目开发只打包本地依赖
借助 http/2(现在的 cdn 基本都是了),性能不一定受影响,可能因为整体尺寸小了而变得更好了
有 library cdn 后,Bundlerless 更容易做了
在中后台这种不太介意整体尺寸的场景更容易快步推进,但性能问题可解
说下缺点,主要是引入的方式需要改成异步,比如:
- import React from 'react';+ const React = await import('libs/react');
所以,对于某些依赖来说 external (比如 react 和 react-dom)可能更合适,但也有一些自动化的方式可以系统地解决此问题,使用此方案的同时并既然使用老的写法,比如:
渲染前通过先挂载 react 和 react-dom
通过 babel 插件的方式自动编译
总之,终极目标就是让时可以只编译项目代码,依赖全部通过 runtime 的方式引入。
应用集方案
Shared component, library, page, subapp
应用集不一定是微前端方案。
一个应用集之前会有很多的共享,比如:
依赖共享
一个应用依赖另一应用的组件
一个应用依赖另一应用的页面
一个应用依赖另一应用
之前的微前端方案需要提一个中心主应用,而这个方案不一定要有中心主应用,应用之间可以直接共享 chunk,当然也可以提一个虚拟不对外的应用,只做模块的生产,供其他应用消费。
注:只适用于分开独立打包发布的应用集,如果是合在一起打包发布,用 monorepo 更合适。
微前端方案改进
Federated Modules 对于微前端而言,在加载策略上也能有一些改进。
之前画的这张微前端需要解决的问题的图里,
最下面的 “公共依赖加载” 一直是没有非常优雅的方案,比如 A 应用依赖 antd4,B 应用依赖 antd3,C 应用也依赖 antd3,如何让 B 和 C 的 antd3 不重复打包和加载。借助 Federated Modules 可以比较好地解决此问题。
参考
https://www.bram.us/2020/03/12/introducing-federated-modules-in-webpack-5/
https://indepth.dev/webpack-5-module-federation-a-game-changer-in-javascript-architecture/
https://zhuanlan.zhihu.com/p/115403616
https://github.com/mizx/mfe-webpack-demo
https://github.com/module-federation
https://github.com/sorrycc/test-federated-modules